/*
  Part of the MasterTool3D project - http://code.google.com/p/master-tool-3d

  Copyright (c) 2011 Ingo Pueschl

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation, version 2.1.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA
*/

package techjit.gfx.util;

import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PGraphics;
import techjit.gfx.util.geo.Vector;
import techjit.util.RuntimeParams;

public class CoordinateSystemDrawer {

	// FIELDS
	private static float DIAMETER_OF_UNIT_CROSS;
	private static float CONE_LENGTH;
	private static float CONE_DIAMETER;

	private static int PIXEL_UNIT_2D = 100;
	private static int PIXEL_DIAMETER_OF_UNIT_CROSS_2D = 20;
	private static int STROKE_WEIGHT_2D = 1;
	private static int ARROW_TIP_LENGTH_2D = 30;
	private static int ARROW_TIP_DIAMETER_2D = 20;

	// METHODS
	public static void draw(PApplet p, float minX, float minY, float minZ,
			float maxX, float maxY, float maxZ) {
		CONE_DIAMETER = RuntimeParams.COORDINATE_SYSTEM_DRAWER__CONE_DIAMETER;
		CONE_LENGTH = RuntimeParams.COORDINATE_SYSTEM_DRAWER__CONE_LENGTH;
		DIAMETER_OF_UNIT_CROSS = RuntimeParams.COORDINATE_SYSTEM_DRAWER__DIAMETER_OF_UNIT_CROSS;
		final int X_AXIS_COLOR = RuntimeParams.COORDINATE_SYSTEM_DRAWER__X_AXIS_COLOR;
		final int Y_AXIS_COLOR = RuntimeParams.COORDINATE_SYSTEM_DRAWER__Y_AXIS_COLOR;
		final int Z_AXIS_COLOR = RuntimeParams.COORDINATE_SYSTEM_DRAWER__Z_AXIS_COLOR;

		p.pushStyle();
		{

			p.colorMode(PConstants.RGB, 1);

			// x axis in red
			PU.strokeAndFill(p, X_AXIS_COLOR);
			drawAxis(p, minX, maxX);

			// y axis in green
			p.pushMatrix();
			{
				p.rotateZ(PApplet.radians(90));
				PU.strokeAndFill(p, Y_AXIS_COLOR);
				drawAxis(p, minY, maxY);
			}
			p.popMatrix();

			// z axis in blue
			p.pushMatrix();
			{
				p.rotateY(PApplet.radians(-90));
				PU.strokeAndFill(p, Z_AXIS_COLOR);
				drawAxis(p, minZ, maxZ);
			}
			p.popMatrix();

		}
		p.popStyle();
	}

	private static void drawAxis(PApplet p, float start, float end) {
		// line from start to end
		PU.line(p, new Vector(start, 0, 0), new Vector(end, 0, 0));

		// unit crosses
		int numOfNegativeCrosses = PApplet.abs((int) (start));
		int numOfPositiveCrosses = (int) (end);

		p.pushMatrix();
		{
			PU.translate(p, new Vector(-numOfNegativeCrosses, 0, 0));
			for (int i = -numOfNegativeCrosses; i <= numOfPositiveCrosses; i++) {
				if (i != 0) {
					drawUnitCross(p);
				}
				if (i < numOfPositiveCrosses) {
					PU.translate(p, new Vector(1, 0, 0));
				}
			}
		}
		p.popMatrix();

		p.pushMatrix();
		{
			PU.translate(p, new Vector(end, 0, 0));
			ConeDrawer.draw(p, CONE_LENGTH, CONE_DIAMETER);
		}
		p.popMatrix();

	}

	public static void drawAxis2D(PGraphics p, float start, float end) {
		// line from start to end
		// <>
		// PU.line(p, new Vector(start, 0, 0), new Vector(end, 0, 0));
		// ==>
		p.strokeWeight(STROKE_WEIGHT_2D);
		p.line(start, 0, end, 0);
		// </>

		// unit crosses
		int numOfNegativeCrosses = PApplet.abs((int) (start));
		int numOfPositiveCrosses = (int) (end);

		p.pushMatrix();
		{
			// <>
			// PU.translate(p, new Vector(-numOfNegativeCrosses, 0, 0));
			// ==>
			p.translate(-numOfNegativeCrosses * PIXEL_UNIT_2D, 0);
			// </>
			for (int i = -numOfNegativeCrosses; i <= numOfPositiveCrosses; i++) {
				if (i != 0) {
					drawUnitCross2D(p);
				}
				if (i < numOfPositiveCrosses) {
					// <>
					// PU.translate(p, new Vector(1, 0, 0));
					// ==>
					p.translate(PIXEL_UNIT_2D, 0);
					// </>
				}
			}
		}
		p.popMatrix();

		p.pushMatrix();
		p.pushStyle();
		{
			// <>
			// PU.translate(p, new Vector(end, 0, 0));
			// ConeDrawer.draw(p, CONE_LENGTH, CONE_DIAMETER);
			// ==>
			p.noStroke();
			p.translate(end, 0);
			p.beginShape(PConstants.POLYGON);
			{
				p.vertex(-ARROW_TIP_LENGTH_2D, -ARROW_TIP_DIAMETER_2D / 2);
				p.vertex(0, 0);
				p.vertex(-ARROW_TIP_LENGTH_2D, ARROW_TIP_DIAMETER_2D / 2);

			}
			p.endShape();
			// </>
		}
		p.popStyle();
		p.popMatrix();

	}

	private static void drawUnitCross(PApplet p) {
		float diameter = DIAMETER_OF_UNIT_CROSS;

		// vertical line
		p.pushMatrix();
		{
			p.rotateZ(PApplet.radians(90));
			PU.line(p, new Vector(-diameter / 2, 0, 0), new Vector(
					diameter / 2, 0, 0));
		}
		p.popMatrix();

		// horizontal line
		p.pushMatrix();
		{
			p.rotateY(PApplet.radians(-90));
			PU.line(p, new Vector(-diameter / 2, 0, 0), new Vector(
					diameter / 2, 0, 0));
		}
		p.popMatrix();

	}

	private static void drawUnitCross2D(PGraphics p) {
		float diameter = PIXEL_DIAMETER_OF_UNIT_CROSS_2D;

		// vertical line
		p.pushMatrix();
		{
			// <>
			// p.rotateZ(PApplet.radians(90));
			// ==>
			p.rotate(PApplet.radians(90));
			// </>
			// <>
			// PU.line(p, new Vector(-diameter / 2, 0, 0), new Vector(
			// diameter / 2, 0, 0));
			// ==>
			p.line(-diameter / 2, 0, diameter / 2, 0);
			// </>
		}
		p.popMatrix();

		// // horizontal line
		// p.pushMatrix();
		// {
		// p.rotateY(PApplet.radians(-90));
		// PU.line(p, new Vector(-diameter / 2, 0, 0), new Vector(
		// diameter / 2, 0, 0));
		// }
		// p.popMatrix();

	}

}
